﻿/*
   Open Intel 
   Copyright © 2011 – ISC. All Rights Reserved.
*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;

namespace OI.Controls
{
    public partial class Navigator : UserControl
    {
        #region events

        public event NavModeEventHandler ModeChanged;

        public event NavZoomEventHandler Zoomed;

        public event NavPanEventHandler Panned;

        #endregion

        #region private members

        bool IsEntered = false;

        bool HasMouseCapture = false;

        DispatcherTimer PanTimer
        {
            get
            {
                if (_PanTimer == null)
                {
                    _PanTimer = new DispatcherTimer();
                    _PanTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
                    _PanTimer.Tick += PanTimer_Tick;
                }
                return _PanTimer;
            }
        }
        DispatcherTimer _PanTimer;

        Point PanVector;

        #endregion

        public Navigator()
        {
            InitializeComponent();
        }

        private void OnMouseEnter(object sender, MouseEventArgs e)
        {
            if (!HasMouseCapture)
            {
                storyNormal.Storyboard.Pause();
                storyMouseOver.Storyboard.Begin();
            }
            IsEntered = true;
        }

        private void OnMouseLeave(object sender, MouseEventArgs e)
        {
            if (!HasMouseCapture)
            {
                storyMouseOver.Storyboard.Pause();
                storyNormal.Storyboard.Begin();
            }
            IsEntered = false;
        }

        private void Road_Checked(object sender, RoutedEventArgs e)
        {
            if (ModeChanged != null) { ModeChanged(this, new NavModeEventArgs("r")); }
        }

        private void Aerial_Checked(object sender, RoutedEventArgs e)
        {
            if (ModeChanged != null) { ModeChanged(this, new NavModeEventArgs("a")); }
        }

        private void Hybrid_Checked(object sender, RoutedEventArgs e)
        {
            if (ModeChanged != null) { ModeChanged(this, new NavModeEventArgs("h")); }
        }

        private void compass_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!HasMouseCapture)
            {
                HasMouseCapture = compass.CaptureMouse();
                if (HasMouseCapture)
                {
                    Point pv = e.GetPosition(compass);

                    Normalize(ref pv);

                    PanVector = pv;
                    if (Panned != null)
                    {
                        Panned(this, new NavPanEventArgs(PanVector));
                    }

                    PanTimer.Start();
                }
            }
        }

        private void Normalize(ref Point pv)
        {
            // adjust relative to compass center
            pv.X -= compass.Width / 2.0;
            pv.Y -= compass.Height / 2.0;

            // invert y axis for mapping
            pv.Y *= -1;

            // normalize to compass dimensions
            pv.X /= compass.Width;
            pv.Y /= compass.Height;
        }

        void PanTimer_Tick(object sender, EventArgs e)
        {
            if (Panned != null)
            {
                Panned(this, new NavPanEventArgs(PanVector));
            }
        }
        
        private void compass_MouseMove(object sender, MouseEventArgs e)
        {
            if (HasMouseCapture)
            {
                Point pv = e.GetPosition(compass);

                Normalize(ref pv);

                PanVector = pv;
            }
        }

        private void compass_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (HasMouseCapture)
            {
                PanTimer.Stop();
                compass.ReleaseMouseCapture();
                HasMouseCapture = false;
                if (!IsEntered)
                {
                    storyMouseOver.Storyboard.Pause();
                    storyNormal.Storyboard.Begin();
                }
            }
        }

        private void zoomIn_Click(object sender, RoutedEventArgs e)
        {
            if (Zoomed != null) { Zoomed(this, new NavZoomEventArgs(1.0)); }
        }

        private void zoomOut_Click(object sender, RoutedEventArgs e)
        {
            if (Zoomed != null) { Zoomed(this, new NavZoomEventArgs(-1.0)); }
        }
    }

    public class NavModeEventArgs : EventArgs
    {
        public string Mode { get; private set; }
        public NavModeEventArgs(string mode) { Mode = mode; }
    }

    public delegate void NavModeEventHandler(object sender, NavModeEventArgs e);

    public class NavZoomEventArgs : EventArgs
    {
        public double ZoomChange {get; private set;}
        public NavZoomEventArgs(double z) { ZoomChange = z; }
    }

    public delegate void NavZoomEventHandler(object sender, NavZoomEventArgs e);

    public class NavPanEventArgs : EventArgs
    {
        public Point PanVector { get; private set; }
        public NavPanEventArgs(Point pv) { PanVector = new Point(pv.X, pv.Y); }
    }

    public delegate void NavPanEventHandler(object sender, NavPanEventArgs e);


}
